package com.codebattery.service;

import com.codebattery.repository.BaseRepository;
import com.codebattery.domain.entity.EntityBase;
import com.codebattery.domain.model.SimpleFilterResolver;

import com.codebattery.util.BeanCopyUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import java.util.Optional;

public abstract class BaseService<T extends EntityBase, ID extends Serializable> {

    public abstract BaseRepository<T, ID> repository();

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

//    @Transactional(readOnly = true)
//    public Page<T> filter(SimpleFilterResolver<T> filterResolver) {
//        return repository().findAll(filterResolver.genSpecification(), filterResolver.genPageRequest());
//    }

    public List<T> find(Specification<T> specification){
        return repository().findAll(specification);
    }

    public Page<T> find(Specification<T> specification, Pageable pageable){
        return repository().findAll(specification, pageable);
    }

    public T get(ID id) {
        T entity = null;
        Optional<T> optional = repository().findById(id);
        if(optional.isPresent()){
            entity = optional.get();
        }
        return entity;
    }

    @Transactional
    public T save(T entity) {
        entity.setCreateTime(new Date());
        return repository().save(entity);
    }

    @Transactional
    public T update(T entity) throws IllegalAccessException {
        Field idField = ReflectionUtils.findField(entity.getClass(), new ReflectionUtils.AnnotationFieldFilter(Id.class));
        idField.setAccessible(true);
        EntityBase entityBase = getEntityManager().find(entity.getClass(), idField.get(entity));
        BeanCopyUtil.beanCopy(entity,entityBase);
        entityBase.setUpdateTime(new Date());
        getEntityManager().merge(entityBase);
        getEntityManager().flush();
        return (T) entityBase;
    }
}